﻿using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static System.Formats.Asn1.AsnWriter;

namespace FractalTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }

        private void OutCanvas_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            var pw = OutCanvas.ActualWidth;
            var ph = OutCanvas.ActualHeight;
            var data = DataContext as MainWindowViewModel;
            var p = e.GetPosition(DisplayImage);
            data.MouseX = p.X;
            data.MouseY = p.Y;
            //左键拖动
            if (e.LeftButton == MouseButtonState.Pressed && e.MiddleButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released)
            {
                //中心偏移
                var dx = (p.X - mouseLeftPoint.X);
                var dy = (mouseLeftPoint.Y - p.Y);
                data.PX -= dx;
                data.PY -= dy;
                var originScale = 2.0 / ph;
                data.CX = -0.5 + data.PX * originScale / data.PScale;
                data.CY = data.PY * originScale / data.PScale;
                mouseLeftPoint.X = p.X;
                mouseLeftPoint.Y = p.Y;

                data.DrawFractal1();
            }
            e.Handled = true;
        }

        private void OutCanvas_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            var data = DataContext as MainWindowViewModel;
            var scale = (e.Delta > 0 ? 1.1 : 0.9) * data.PScale;
            var pw = OutCanvas.ActualWidth;
            var ph = OutCanvas.ActualHeight;
            var originScale = 2.0 / ph;
            var p = e.GetPosition(DisplayImage);
            Point center = new Point(data.PX, data.PY);
            ZoomAt(p, scale / data.PScale, ref center, (int)pw, (int)ph);
            data.PScale = scale;
            data.CX = -0.5 + center.X * originScale / data.PScale;
            data.CY = center.Y * originScale / data.PScale;
            data.PX = center.X;
            data.PY = center.Y;
            data.DrawFractal1();
            e.Handled = true;
        }
        /// <summary>
        /// 以鼠标点为中心缩放，并返回缩放后画面中心的像素坐标
        /// </summary>
        /// <param name="mouse">鼠标像素坐标</param>
        /// <param name="center">缩放前的显示中心像素坐标</param>
        /// <param name="oldScale">缩放前比例</param>
        /// <param name="newScale">缩放后比例</param>

        /// <param name="width">画布宽度</param>
        /// <param name="height">画布高度</param>
        /// <returns>缩放后画面中心的像素坐标 (centerPixelX, centerPixelY)</returns>
        public void ZoomAt(
            Point mouse,
            double scale,
            ref Point center,
            int width, int height)
        {

            double dx = (mouse.X - width / 2.0);
            double dy = (-mouse.Y + height / 2.0);
            // 1. 鼠标点对应的复平面坐标
            double px = dx + center.X;
            double py = dy + center.Y;
            // 2. 缩放后新的复平面中心
            double newCenterX = px * scale - dx;
            double newCenterY = py * scale - dy;
            center = new Point(newCenterX, newCenterY);
        }
        Point mouseLeftPoint;
        private void OutCanvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            mouseLeftPoint = e.GetPosition(DisplayImage);
            e.Handled = true;
        }
    }
}